package readAndWrite;

//PV操作类
class lockOperate {
    int count = 0; //信号量
    lockOperate(){} //构造方法
    lockOperate(int a){
        count = a;
    }

    public synchronized void Wait(){  //synchronized保证操作的原子性
        count--;
        if(count<0){
            try {
                this.wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
    }

    public synchronized void Signal(){
        count++;
        if(count<=0){  //如果有进程阻塞
            this.notify();
        }
    }
}

//初始化各信号量
class Semaphore {
    static lockOperate empty = new lockOperate(16); //empty信号量
    static lockOperate full = new lockOperate(0);  //full信号量
    static lockOperate mutex = new lockOperate(1);  //读写互斥信号量
    static int[] buffer =new int[15]; //缓冲区
}

//生产者类
class Producer implements Runnable{
    int count=0;
    public void run(){
        while (count<20){
            Semaphore.empty.Wait();
            Semaphore.mutex.Wait();
            //进入临界区
            System.out.println("写者开始写"+count);
            int index = count % 15; //求出资源所在缓冲区哪个位置
            Semaphore.buffer[index] = count;
            System.out.println("写者在缓冲区"+index+"中写完"+count);
            count++;
            try {
                Thread.sleep(10);
            }catch (InterruptedException e){
                e.printStackTrace();
            }
            //退出临界区
            Semaphore.mutex.Signal();
            Semaphore.full.Signal();
        }
    }
}

//消费者类
class Consumer implements Runnable{
    int count = 0;
    public void run(){
        while (count<20){
            Semaphore.full.Wait();
            Semaphore.mutex.Wait();
            //进入临界区
            System.out.println("读者开始读"+count);
            int index = count % 15;
            int value = Semaphore.buffer[index];
            System.out.println("读者在缓冲区"+index+"中读完"+value);
            count++;
            try {
                Thread.sleep(10);
            }catch (InterruptedException e){
                e.printStackTrace();
            }          //瑞出临界区
            Semaphore.mutex.Signal();
            Semaphore.empty.Signal();
        }
    }
}

public class test {
    public static void main(String[] args) {
        Producer writer = new Producer();
        Consumer reader = new Consumer();
        Thread p2 = new Thread(reader);
        Thread p1 = new Thread(writer);
        p1.start();
        p2.start();
    }
}
